package com.example.common.config;

import org.apache.commons.collections.CollectionUtils;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

/**
 * @Author Peng Yisheng
 * @Date 2024/11/25 0:46
 * @Description 动态服务缓存配置管理类
 */
public class DynamicConfigManager {

    private DynamicConfigManager() {
    }

    private static class SingletonHolder {
        private static final DynamicConfigManager INSTANCE = new DynamicConfigManager();  // 单例
    }

    public static DynamicConfigManager getInstance() {
        return SingletonHolder.INSTANCE;
    }

    // 服务定义缓存: uniqueId对应一个服务定义, uniqueId=serviceId:version，
    private ConcurrentHashMap<String /* uniqueId */ , ServiceDefinition> serviceDefinitionMap = new ConcurrentHashMap<>();

    // 服务实例缓存：uniqueId对应一组服务实例
    private ConcurrentHashMap<String /* uniqueId */ , Set<ServiceInstance>> serviceInstanceMap = new ConcurrentHashMap<>();

    // 规则缓存：ruleId
    private ConcurrentHashMap<String /* ruleId */ , Rule> ruleMap = new ConcurrentHashMap<>();
    // path: 一个路径只会对应一个规则
    private ConcurrentHashMap<String /* path */ , Rule> pathRuleMap = new ConcurrentHashMap<>();
    // 规则列表缓存，一个服务可以对应多个规则：一个服务有多个路径，一个路径对应一个规则，反之，一个规则只属于一个服务
    private ConcurrentHashMap<String /* serviceId */ , List<Rule>> serviceRuleMap = new ConcurrentHashMap<>();


    /***************** 	对ServiceDefinition缓存进行操作的系列方法 	***************/
    public ServiceDefinition getServiceDefinition(String uniqueId) {
        return serviceDefinitionMap.get(uniqueId);
    }

    public void putServiceDefinition(String uniqueId, ServiceDefinition serviceDefinition) {
        serviceDefinitionMap.put(uniqueId, serviceDefinition);
    }

    public void removeServiceDefinition(String uniqueId) {
        serviceDefinitionMap.remove(uniqueId);
    }

    /***************** 	对ServiceInstance缓存进行操作的系列方法 	***************/
    public void addServiceInstance(String uniqueId, Set<ServiceInstance> serviceInstanceSet) {
        serviceInstanceMap.put(uniqueId, serviceInstanceSet);
    }

    public Set<ServiceInstance> getServiceInstanceByUniqueId(String uniqueId, boolean gray) {
        Set<ServiceInstance> serviceInstances = serviceInstanceMap.get(uniqueId);
        if (CollectionUtils.isEmpty(serviceInstances)) {
            return Collections.emptySet();
        }

        // 灰度流量请求只会进入灰度实例
        if (gray) {
            return serviceInstances.stream()
                    .filter(ServiceInstance::isGray)
                    .collect(Collectors.toSet());
        }

        return serviceInstances;
    }

    /***************** 	对规则缓存进行操作的系列方法 	***************/
    public void putAllRule(List<Rule> ruleList) {
        ConcurrentHashMap<String, Rule> newRuleMap = new ConcurrentHashMap<>();
        ConcurrentHashMap<String, Rule> newPathMap = new ConcurrentHashMap<>();
        ConcurrentHashMap<String, List<Rule>> newServiceMap = new ConcurrentHashMap<>();
        for (Rule rule : ruleList) {
            // ruleMap
            newRuleMap.put(rule.getId(), rule);

            // pathRuleMap
            List<String> paths = rule.getPaths();
            for (String path : paths) {
                String key = rule.getServiceId() + "." + path;
                newPathMap.put(key, rule);
            }

            // serviceRuleMap
            newServiceMap.computeIfAbsent(rule.getServiceId(), k -> new ArrayList<>()).add(rule);
        }
        ruleMap = newRuleMap;
        pathRuleMap = newPathMap;
        serviceRuleMap = newServiceMap;
    }

    public Rule getRuleByPath(String path) {
        return pathRuleMap.get(path);
    }

    public List<Rule> getRuleByServiceId(String serviceId) {
        return serviceRuleMap.get(serviceId);
    }
}
